#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"

//p24 p25
//TODO 测试未通过
//./mededata /path/aa.pcm out.aac

int encodeAudio(AVCodecContext *encoderCtx, AVFrame *frame, AVPacket *packet, FILE *dest_fp) {
    int ret = avcodec_send_frame(encoderCtx, frame);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_send_frame failed: %s\n", av_err2str(ret));
        return -1;
    }
    while (ret > 0) {
        ret = avcodec_receive_packet(encoderCtx, packet);
        if (ret = AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return 0;
        } else if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "avcodec_receive_packet failed: %s \n", av_err2str(ret));
            return -1;
        }
        fwrite(packet->data, 1, packet->size, dest_fp);
    }
    return 0;
}

int main(int argc, char **argv) {
    av_log_set_level(AV_LOG_INFO);
    if (argc < 3) {
        av_log(NULL, AV_LOG_ERROR, "Usage: %s <infile> <outfile> \n", argv[0]);
        return -1;
    }

    const char *inFileName = argv[1];
    const char *outFileName = argv[2];

    AVFrame  *frame = av_frame_alloc();
    frame->sample_rate = 48000;
//    frame->channels = 2;
    frame->ch_layout.nb_channels = AV_CH_LAYOUT_STEREO;
    frame->format = AV_SAMPLE_FMT_S16;
    frame->nb_samples = 1024;
    av_frame_get_buffer(frame, 0);

    int ret = 0;
    AVCodec * encoder = avcodec_find_encoder_by_name("aac");
//    AVCodec * encoder = avcodec_find_encoder_by_name("libfdk_aac");
//    AVCodec * encoder = avcodec_find_encoder_by_name("libmp3lame");
    if (encoder == NULL) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_find_encoder_by_name is null failed\n");
        ret = -1;
        goto end;
    }

    AVCodecContext  * encoderCtx = avcodec_alloc_context3(encoder);
    if (encoderCtx == NULL) {
        av_log(NULL, AV_LOG_ERROR, "alloc encoder context failed!\n");
        ret = -1;
        goto end;
    }
    encoderCtx->sample_fmt = frame->format;
    encoderCtx->sample_rate = frame->sample_rate;
//    encoderCtx->channels = frame->channels;
    encoderCtx->ch_layout.nb_channels = frame->ch_layout.nb_channels;
    
    ret = avcodec_open2(encoderCtx, encoder, NULL);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_open2 failed: %d\n", ret);
        goto end;
    }


    FILE *src_fp = fopen(inFileName, "wb+");
    if (src_fp == NULL) {
        av_log(NULL, AV_LOG_ERROR, "fopen failed:%s\n", inFileName);
        ret = -1;
        goto end;
    }

    FILE *dest_fp = fopen(outFileName, "wb+");
    if (dest_fp == NULL) {
        av_log(NULL, AV_LOG_ERROR, "fopen failed:%s\n", outFileName);
        ret = -1;
        goto end;
    }
    AVPacket *packet = av_packet_alloc();
    if (!packet) {
        av_log(NULL, AV_LOG_ERROR, "av_packet_alloc failed\n");
        ret = -1;
        goto end;
    }
    while (1) {
        int readSize = fread(frame->data[0], 1, frame->linesize[0], src_fp);
        if (readSize == 0) {
            av_log(NULL, AV_LOG_ERROR, "fread\n");
            break;
        }
        encodeAudio(encoderCtx, frame, packet, dest_fp);
    }
    encodeAudio(encoderCtx, NULL, packet, dest_fp);

    end:
    if (frame) {
        av_frame_free(&frame);
    }
    if (encoderCtx) {
        avcodec_free_context(&encoderCtx);
    }
    if (src_fp) {
        fclose(src_fp);
    }
    if (dest_fp) {
        fclose(dest_fp);
    }
    return ret;
}





